/**
 * ex1. 变量声明
 *
 * @author cyy
 * @date 2020/10/25
 */
package main

import "fmt"

var (
	name1 = 1
	name2 = 2
	name3 = ""
)

func main() {
	/*
		单变量声明，区别在于后者只允许在函数中使用
			var [变量名] ([数据类型]) ( = [变量值])
			[变量名] := [变量值]
	*/
	var a string = "数据类型可省略，会自动推导，句末的分号也会自动补充"
	b := 1
	fmt.Printf("单变量声明, a = %s, b = %d\n", a, b)

	/*
		多变量声明，区别在于①限定了所有变量的数据类型一致，③只能应用于函数中
			① var [变量名1], [变量名2](, ..., [变量名n]) ([数据类型])
			② var (
				[变量名1] ([数据类型1]) ( = [变量值1])
				[变量名2] ([数据类型2]) ( = [变量值2])
				...
			)
			③ [变量名1], [变量名2](, ..., [变量名n]) := [变量值1](, [变量值3], ..., [变量值n])
	*/
	var c1, c2 = 1, 2
	var (
		d1 int    = 3
		d2 string = "4"
	)
	e1, e2 := 5, "6"
	fmt.Printf("多变量声明, c1 = %d, c2 = %d, d1 = %d, d2 = %s, e1 = %d, e2 = %s\n", c1, c2, d1, d2, e1, e2)

	/*
		匿名变量，写作“_”，不占用命名空间，因为不会为其分配内存所以匿名变量之间不存在重复声明
	*/
	var f1, _ = test(c1, c2)
	var _, f2 = test(c1, c2)
	fmt.Printf("匿名变量, f1  = %d, f2 = %d\n", f1, f2)

	/*
		go的打印包fmt，类似Java的System类区别在于前者允许多个入参
			System.out.println()	-	fmt.Println()
			System.out.print() 		- 	fmt.Print()
			System.out.printf()		-	fmt.Printf()
	*/
	fmt.Print("fmt", "支持多个入参")
	fmt.Println("fmt", "支持多个入参")
	fmt.Printf("a = %s, 数据类型为%T, b = %d, 数据类型为%T\n", a, a, b, b)

	/*
		常量const，一旦赋值就不能被改变
		iota，go的常量计数器，只能在常量的表达式中使用
			iota在const关键字出现时将被重置为0，const中每新增一行常量声明（即使该行未声明为iota也算作在内），就会将iota计数一次，也可理解为const语句块中的行索引
	*/
	const k = 0
	const k0 = iota
	const (
		x = 0 // 0
		y = 1 // 1
		z     // 1
	)
	fmt.Printf("x = %d, y = %d, z = %d\n", x, y, z)

	const (
		k1 = iota // 0
		k2        // 1
		k3        // 2
	)
	const (
		k4 = iota // 0
		k5 = 1
		k6 = iota // 2
	)
	fmt.Printf("常量const, k = %d\n", k)
	fmt.Printf("常量计数器iota, k0 = %d\n", k0)
	fmt.Printf("常量计数器iota, k1 = %d, k2 = %d, k3 = %d\n", k1, k2, k3)
	fmt.Printf("常量计数器iota, k4 = %d, k5 = %d, k6 = %d\n", k4, k5, k6)

	const (
		l1, l2 = iota, iota + 1 // 0 1
		l3, l4                  // 1 2
		l5, l6                  // 2 3
	)
	fmt.Printf("常量计数器iota：\nl1 = %d, l2 = %d, \nl3 = %d, l4 = %d, \nl5 = %d, l6 = %d\n", l1, l2, l3, l4, l5, l6)

}

/*
	函数定义
		func [函数名](入参) (返回结果) {
			// 函数体
		}
*/
func test(a int, b int) (int, int) {
	return a + b, a - b
}
